package com.mini.grpc.examples.helloworld;

import com.mini.grpc.client.AbstractStub;
import com.mini.grpc.client.CallOptions;
import com.mini.grpc.client.ClientCall;
import com.mini.grpc.client.MiniGrpcChannel;
import com.mini.grpc.common.Metadata;
import com.mini.grpc.common.MethodDescriptor;
import com.mini.grpc.common.Status;
import com.mini.grpc.common.StreamObserver;
import com.mini.grpc.serialization.StringMarshaller;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/**
 * HelloWorld服务的gRPC存根类
 * 实现真正的gRPC调用
 */
public final class HelloWorldServiceGrpc {
    
    private HelloWorldServiceGrpc() {}
    
    public static final String SERVICE_NAME = "helloworld.HelloWorldService";
    
    // 方法描述符定义
    public static final MethodDescriptor<String, String> SAY_HELLO_METHOD =
        MethodDescriptor.<String, String>newBuilder()
            .setFullMethodName(SERVICE_NAME + "/sayHello")
            .setMethodType(MethodDescriptor.MethodType.UNARY)
            .setRequestMarshaller(StringMarshaller.INSTANCE)
            .setResponseMarshaller(StringMarshaller.INSTANCE)
            .build();
    
    public static final MethodDescriptor<String, String> SAY_HELLO_SERVER_STREAM_METHOD =
        MethodDescriptor.<String, String>newBuilder()
            .setFullMethodName(SERVICE_NAME + "/sayHelloServerStream")
            .setMethodType(MethodDescriptor.MethodType.SERVER_STREAMING)
            .setRequestMarshaller(StringMarshaller.INSTANCE)
            .setResponseMarshaller(StringMarshaller.INSTANCE)
            .build();
    
    public static final MethodDescriptor<String, String> SAY_HELLO_CLIENT_STREAM_METHOD =
        MethodDescriptor.<String, String>newBuilder()
            .setFullMethodName(SERVICE_NAME + "/sayHelloClientStream")
            .setMethodType(MethodDescriptor.MethodType.CLIENT_STREAMING)
            .setRequestMarshaller(StringMarshaller.INSTANCE)
            .setResponseMarshaller(StringMarshaller.INSTANCE)
            .build();
    
    public static final MethodDescriptor<String, String> SAY_HELLO_BIDI_STREAM_METHOD =
        MethodDescriptor.<String, String>newBuilder()
            .setFullMethodName(SERVICE_NAME + "/sayHelloBidiStream")
            .setMethodType(MethodDescriptor.MethodType.BIDI_STREAMING)
            .setRequestMarshaller(StringMarshaller.INSTANCE)
            .setResponseMarshaller(StringMarshaller.INSTANCE)
            .build();
    
    /**
     * 服务绑定基类
     */
    public static abstract class HelloWorldServiceImplBase {
        
        /**
         * 一元调用方法
         */
        public String sayHello(String request) {
            throw new UnsupportedOperationException("Method not implemented: sayHello");
        }
        
        /**
         * 服务端流式调用方法
         */
        public void sayHelloServerStream(String request, StreamObserver<String> responseObserver) {
            throw new UnsupportedOperationException("Method not implemented: sayHelloServerStream");
        }
        
        /**
         * 客户端流式调用方法
         */
        public StreamObserver<String> sayHelloClientStream(StreamObserver<String> responseObserver) {
            throw new UnsupportedOperationException("Method not implemented: sayHelloClientStream");
        }
        
        /**
         * 双向流式调用方法
         */
        public StreamObserver<String> sayHelloBidiStream(StreamObserver<String> responseObserver) {
            throw new UnsupportedOperationException("Method not implemented: sayHelloBidiStream");
        }
        
        /**
         * 绑定服务到服务器
         */
        public final com.mini.grpc.server.ServerServiceDefinition bindService() {
            return com.mini.grpc.server.ServerServiceDefinition.builder(SERVICE_NAME)
                .addMethod(SAY_HELLO_METHOD, new UnaryMethodHandler<>(this::sayHello))
                .addMethod(SAY_HELLO_SERVER_STREAM_METHOD, new ServerStreamingMethodHandler<>(this::sayHelloServerStream))
                .addMethod(SAY_HELLO_CLIENT_STREAM_METHOD, new ClientStreamingMethodHandler<>(this::sayHelloClientStream))
                .addMethod(SAY_HELLO_BIDI_STREAM_METHOD, new BidiStreamingMethodHandler<>(this::sayHelloBidiStream))
                .build();
        }
    }

    // 方法处理器实现
    private static class UnaryMethodHandler<ReqT, RespT> implements com.mini.grpc.server.ServerCallHandler<ReqT, RespT> {
        private final java.util.function.Function<ReqT, RespT> method;
        
        public UnaryMethodHandler(java.util.function.Function<ReqT, RespT> method) {
            this.method = method;
        }
        
        @Override
        public com.mini.grpc.server.ServerCall.Listener<ReqT> startCall(
                com.mini.grpc.server.ServerCall<ReqT, RespT> call, 
                Metadata headers) {
            return new com.mini.grpc.server.ServerCall.Listener<ReqT>() {
                private ReqT request;
                
                @Override
                public void onMessage(ReqT message) {
                    this.request = message;
                }
                
                @Override
                public void onHalfClose() {
                    try {
                        RespT response = method.apply(request);
                        call.sendHeaders(new Metadata());
                        call.sendMessage(response);
                        call.close(com.mini.grpc.common.Status.OK, new Metadata());
                    } catch (Exception e) {
                        call.close(com.mini.grpc.common.Status.INTERNAL.withDescription(e.getMessage()), new Metadata());
                    }
                }
                
                @Override
                public void onCancel() {
                    // 处理取消
                }
                
                @Override
                public void onComplete() {
                    // 处理完成
                }
            };
        }
    }
    
    private static class ServerStreamingMethodHandler<ReqT, RespT> implements com.mini.grpc.server.ServerCallHandler<ReqT, RespT> {
        private final java.util.function.BiConsumer<ReqT, StreamObserver<RespT>> method;
        
        public ServerStreamingMethodHandler(java.util.function.BiConsumer<ReqT, StreamObserver<RespT>> method) {
            this.method = method;
        }
        
        @Override
        public com.mini.grpc.server.ServerCall.Listener<ReqT> startCall(
                com.mini.grpc.server.ServerCall<ReqT, RespT> call, 
                Metadata headers) {
            return new com.mini.grpc.server.ServerCall.Listener<ReqT>() {
                private ReqT request;
                
                @Override
                public void onMessage(ReqT message) {
                    this.request = message;
                }
                
                @Override
                public void onHalfClose() {
                    call.sendHeaders(new Metadata());
                    StreamObserver<RespT> responseObserver = new StreamObserver<RespT>() {
                        @Override
                        public void onNext(RespT value) {
                            call.sendMessage(value);
                        }
                        
                        @Override
                        public void onError(Throwable t) {
                            call.close(com.mini.grpc.common.Status.INTERNAL.withDescription(t.getMessage()), new Metadata());
                        }
                        
                        @Override
                        public void onCompleted() {
                            call.close(com.mini.grpc.common.Status.OK, new Metadata());
                        }
                    };
                    
                    try {
                        method.accept(request, responseObserver);
                    } catch (Exception e) {
                        responseObserver.onError(e);
                    }
                }
                
                @Override
                public void onCancel() {
                    // 处理取消
                }
                
                @Override
                public void onComplete() {
                    // 处理完成
                }
            };
        }
    }
    
    private static class ClientStreamingMethodHandler<ReqT, RespT> implements com.mini.grpc.server.ServerCallHandler<ReqT, RespT> {
        private final java.util.function.Function<StreamObserver<RespT>, StreamObserver<ReqT>> method;
        
        public ClientStreamingMethodHandler(java.util.function.Function<StreamObserver<RespT>, StreamObserver<ReqT>> method) {
            this.method = method;
        }
        
        @Override
        public com.mini.grpc.server.ServerCall.Listener<ReqT> startCall(
                com.mini.grpc.server.ServerCall<ReqT, RespT> call, 
                Metadata headers) {
            call.sendHeaders(new Metadata());
            
            StreamObserver<RespT> responseObserver = new StreamObserver<RespT>() {
                @Override
                public void onNext(RespT value) {
                    call.sendMessage(value);
                }
                
                @Override
                public void onError(Throwable t) {
                    call.close(com.mini.grpc.common.Status.INTERNAL.withDescription(t.getMessage()), new Metadata());
                }
                
                @Override
                public void onCompleted() {
                    call.close(com.mini.grpc.common.Status.OK, new Metadata());
                }
            };
            
            StreamObserver<ReqT> requestObserver = method.apply(responseObserver);
            
            return new com.mini.grpc.server.ServerCall.Listener<ReqT>() {
                @Override
                public void onMessage(ReqT message) {
                    requestObserver.onNext(message);
                }
                
                @Override
                public void onHalfClose() {
                    requestObserver.onCompleted();
                }
                
                @Override
                public void onCancel() {
                    requestObserver.onError(new RuntimeException("Call cancelled"));
                }
                
                @Override
                public void onComplete() {
                    // 处理完成
                }
            };
        }
    }
    
    private static class BidiStreamingMethodHandler<ReqT, RespT> implements com.mini.grpc.server.ServerCallHandler<ReqT, RespT> {
        private final java.util.function.Function<StreamObserver<RespT>, StreamObserver<ReqT>> method;
        
        public BidiStreamingMethodHandler(java.util.function.Function<StreamObserver<RespT>, StreamObserver<ReqT>> method) {
            this.method = method;
        }
        
        @Override
        public com.mini.grpc.server.ServerCall.Listener<ReqT> startCall(
                com.mini.grpc.server.ServerCall<ReqT, RespT> call, 
                Metadata headers) {
            call.sendHeaders(new Metadata());
            
            StreamObserver<RespT> responseObserver = new StreamObserver<RespT>() {
                @Override
                public void onNext(RespT value) {
                    call.sendMessage(value);
                }
                
                @Override
                public void onError(Throwable t) {
                    call.close(com.mini.grpc.common.Status.INTERNAL.withDescription(t.getMessage()), new Metadata());
                }
                
                @Override
                public void onCompleted() {
                    call.close(com.mini.grpc.common.Status.OK, new Metadata());
                }
            };
            
            StreamObserver<ReqT> requestObserver = method.apply(responseObserver);
            
            return new com.mini.grpc.server.ServerCall.Listener<ReqT>() {
                @Override
                public void onMessage(ReqT message) {
                    requestObserver.onNext(message);
                }
                
                @Override
                public void onHalfClose() {
                    requestObserver.onCompleted();
                }
                
                @Override
                public void onCancel() {
                    requestObserver.onError(new RuntimeException("Call cancelled"));
                }
                
                @Override
                public void onComplete() {
                    // 处理完成
                }
            };
        }
    }
    
    /**
     * 阻塞存根 - 使用真正的gRPC调用
     */
    public static final class HelloWorldServiceBlockingStub extends AbstractStub<HelloWorldServiceBlockingStub> {
        
        private HelloWorldServiceBlockingStub(MiniGrpcChannel channel, CallOptions callOptions) {
            super(channel, callOptions);
        }
        
        @Override
        protected HelloWorldServiceBlockingStub build(MiniGrpcChannel channel, CallOptions callOptions) {
            return new HelloWorldServiceBlockingStub(channel, callOptions);
        }
        
        @Override
        protected HelloWorldServiceBlockingStub thisT() {
            return this;
        }
        
        /**
         * 一元调用 - 真正的gRPC实现
         */
        public String sayHello(String request) {
            System.out.println("=== HelloWorldServiceBlockingStub.sayHello called with request: " + request + " ===");
            
            System.out.println("About to call newCall()");
            ClientCall<String, String> call = newCall(SAY_HELLO_METHOD);
            System.out.println("newCall() returned: " + call);
            System.out.println("Created ClientCall: " + call.getClass().getName());
            
            AtomicReference<String> responseRef = new AtomicReference<>();
            AtomicReference<Status> statusRef = new AtomicReference<>();
            CountDownLatch latch = new CountDownLatch(1);
            
            System.out.println("About to call call.start()");
            System.out.println("Call object details:");
            System.out.println("  - Class: " + call.getClass());
            System.out.println("  - Superclass: " + call.getClass().getSuperclass());
            System.out.println("  - Interfaces: " + java.util.Arrays.toString(call.getClass().getInterfaces()));
            System.out.println("  - toString: " + call.toString());
            
            // 检查是否是代理对象
            if (java.lang.reflect.Proxy.isProxyClass(call.getClass())) {
                System.out.println("  - This is a Proxy class!");
                System.out.println("  - InvocationHandler: " + java.lang.reflect.Proxy.getInvocationHandler(call));
            }
            
            // 使用反射检查start方法
            try {
                java.lang.reflect.Method startMethod = call.getClass().getMethod("start", ClientCall.Listener.class, Metadata.class);
                System.out.println("Found start method: " + startMethod);
                System.out.println("Declaring class: " + startMethod.getDeclaringClass());
            } catch (Exception e) {
                System.out.println("Error finding start method: " + e.getMessage());
            }
            
            System.out.println("=== ABOUT TO CALL start() ===");
            
            call.start(new ClientCall.Listener<String>() {
                @Override
                public void onMessage(String message) {
                    System.out.println("Received message: " + message);
                    responseRef.set(message);
                }
                
                @Override
                public void onClose(Status status, Metadata trailers) {
                    System.out.println("Call closed with status: " + status);
                    statusRef.set(status);
                    latch.countDown();
                }
            }, new Metadata());
            
            System.out.println("=== start() CALL RETURNED ===");
            
            System.out.println("call.start() completed, about to call request(1)");
            call.request(1);
            
            System.out.println("About to call sendMessage()");
            call.sendMessage(request);
            
            System.out.println("About to call halfClose()");
            call.halfClose();
            
            System.out.println("Waiting for response...");
            
            try {
                if (!latch.await(30, TimeUnit.SECONDS)) {
                    System.out.println("Call timeout!");
                    call.cancel("Timeout", new RuntimeException("Call timeout"));
                    throw new RuntimeException("Call timeout after 30 seconds");
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                call.cancel("Interrupted", e);
                throw new RuntimeException("Call interrupted", e);
            }
            
            Status status = statusRef.get();
            if (status != null && !status.isOk()) {
                throw new RuntimeException("Call failed: " + status);
            }
            
            return responseRef.get();
        }
        
        /**
         * 服务端流式调用 - 真正的gRPC实现
         */
        public void sayHelloServerStream(String request, StreamObserver<String> responseObserver) {
            ClientCall<String, String> call = newCall(SAY_HELLO_SERVER_STREAM_METHOD);
            
            call.start(new ClientCall.Listener<String>() {
                @Override
                public void onMessage(String message) {
                    responseObserver.onNext(message);
                }
                
                @Override
                public void onClose(Status status, Metadata trailers) {
                    if (status.isOk()) {
                        responseObserver.onCompleted();
                    } else {
                        responseObserver.onError(new RuntimeException("Call failed: " + status));
                    }
                }
            }, new Metadata());
            
            call.request(Integer.MAX_VALUE); // 请求接收所有消息
            call.sendMessage(request);
            call.halfClose();
        }
    }
    
    /**
     * 异步存根 - 使用真正的gRPC调用
     */
    public static final class HelloWorldServiceStub extends AbstractStub<HelloWorldServiceStub> {
        
        private HelloWorldServiceStub(MiniGrpcChannel channel, CallOptions callOptions) {
            super(channel, callOptions);
        }
        
        @Override
        protected HelloWorldServiceStub build(MiniGrpcChannel channel, CallOptions callOptions) {
            return new HelloWorldServiceStub(channel, callOptions);
        }
        
        @Override
        protected HelloWorldServiceStub thisT() {
            return this;
        }
        
        /**
         * 异步一元调用 - 真正的gRPC实现
         */
        public void sayHello(String request, StreamObserver<String> responseObserver) {
            ClientCall<String, String> call = newCall(SAY_HELLO_METHOD);
            
            call.start(new ClientCall.Listener<String>() {
                @Override
                public void onMessage(String message) {
                    responseObserver.onNext(message);
                }
                
                @Override
                public void onClose(Status status, Metadata trailers) {
                    if (status.isOk()) {
                        responseObserver.onCompleted();
                    } else {
                        responseObserver.onError(new RuntimeException("Call failed: " + status));
                    }
                }
            }, new Metadata());
            
            call.request(1);
            call.sendMessage(request);
            call.halfClose();
        }
        
        /**
         * 服务端流式调用 - 真正的gRPC实现
         */
        public void sayHelloServerStream(String request, StreamObserver<String> responseObserver) {
            ClientCall<String, String> call = newCall(SAY_HELLO_SERVER_STREAM_METHOD);
            
            call.start(new ClientCall.Listener<String>() {
                @Override
                public void onMessage(String message) {
                    responseObserver.onNext(message);
                }
                
                @Override
                public void onClose(Status status, Metadata trailers) {
                    if (status.isOk()) {
                        responseObserver.onCompleted();
                    } else {
                        responseObserver.onError(new RuntimeException("Call failed: " + status));
                    }
                }
            }, new Metadata());
            
            call.request(Integer.MAX_VALUE);
            call.sendMessage(request);
            call.halfClose();
        }
        
        /**
         * 客户端流式调用 - 真正的gRPC实现
         */
        public StreamObserver<String> sayHelloClientStream(StreamObserver<String> responseObserver) {
            ClientCall<String, String> call = newCall(SAY_HELLO_CLIENT_STREAM_METHOD);
            
            call.start(new ClientCall.Listener<String>() {
                @Override
                public void onMessage(String message) {
                    responseObserver.onNext(message);
                }
                
                @Override
                public void onClose(Status status, Metadata trailers) {
                    if (status.isOk()) {
                        responseObserver.onCompleted();
                    } else {
                        responseObserver.onError(new RuntimeException("Call failed: " + status));
                    }
                }
            }, new Metadata());
            
            call.request(1);
            
            return new StreamObserver<String>() {
                @Override
                public void onNext(String value) {
                    call.sendMessage(value);
                }
                
                @Override
                public void onError(Throwable t) {
                    call.cancel("Client error", t);
                }
                
                @Override
                public void onCompleted() {
                    call.halfClose();
                }
            };
        }
        
        /**
         * 双向流式调用 - 真正的gRPC实现
         */
        public StreamObserver<String> sayHelloBidiStream(StreamObserver<String> responseObserver) {
            ClientCall<String, String> call = newCall(SAY_HELLO_BIDI_STREAM_METHOD);
            
            call.start(new ClientCall.Listener<String>() {
                @Override
                public void onMessage(String message) {
                    responseObserver.onNext(message);
                }
                
                @Override
                public void onClose(Status status, Metadata trailers) {
                    if (status.isOk()) {
                        responseObserver.onCompleted();
                    } else {
                        responseObserver.onError(new RuntimeException("Call failed: " + status));
                    }
                }
            }, new Metadata());
            
            call.request(Integer.MAX_VALUE);
            
            return new StreamObserver<String>() {
                @Override
                public void onNext(String value) {
                    call.sendMessage(value);
                }
                
                @Override
                public void onError(Throwable t) {
                    call.cancel("Client error", t);
                }
                
                @Override
                public void onCompleted() {
                    call.halfClose();
                }
            };
        }
    }
    
    /**
     * 创建阻塞存根
     */
    public static HelloWorldServiceBlockingStub newBlockingStub(MiniGrpcChannel channel) {
        return new HelloWorldServiceBlockingStub(channel, CallOptions.DEFAULT);
    }
    
    /**
     * 创建异步存根
     */
    public static HelloWorldServiceStub newStub(MiniGrpcChannel channel) {
        return new HelloWorldServiceStub(channel, CallOptions.DEFAULT);
    }
} 